home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
workbench
/
tools
/
czesc_3
/
multiuser
/
src
/
library
/
server.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-29
|
18KB
|
784 lines
/************************************************************
* MultiUser - MultiUser Task/File Support System *
* --------------------------------------------------------- *
* Server Process *
* --------------------------------------------------------- *
* © Copyright 1993-1994 Geert Uytterhoeven *
* All Rights Reserved. *
************************************************************/
#include <exec/execbase.h>
#include <exec/alerts.h>
#include <exec/ports.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <utility/tagitem.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/utility.h>
#include <proto/reqtools.h>
#include <libraries/reqtools.h>
#include <string.h>
#include "Memory.h"
#include "Server.h"
#include "Config.h"
#include "Locale.h"
#include "LibHeader.h"
#include "Misc.h"
#include "Task.h"
#include "UserInfo.h"
#include "GroupInfo.h"
#include "Monitor.h"
/*
* Static Routines
*/
static void __saveds ServerProcess(void);
static struct muPrivUserInfo *CheckUser(ULONG user, STRPTR userid, STRPTR pwd, BOOL nopasswd,
BOOL nolog);
static BOOL Passwd(ULONG user, STRPTR oldpwd, STRPTR newpwd);
static struct muPrivUserInfo *GetUserInfo(struct muPrivUserInfo *info, ULONG keytype);
static BOOL Belongs2(struct muUserDef *def, UWORD gid);
static void FillUserInfo(struct muUserDef *def, struct muPrivUserInfo *info);
static BOOL CheckPasswd(ULONG user, STRPTR pwd);
static struct muPrivGroupInfo *GetGroupInfo(struct muPrivGroupInfo *info, ULONG keytype);
static void FillGroupInfo(struct muGroupDef *def, struct muPrivGroupInfo *info);
/*
* Configuration Stuff
*/
extern BPTR PasswdDirLock;
extern BPTR ConfigDirLock;
/*
* Start the Server's Process
*/
struct Process *CreateServer(void)
{
static struct TagItem tags[] = {
NP_Entry, (LONG)ServerProcess,
NP_Name, (LONG)SERVERNAME,
NP_Priority, SERVERPRI,
NP_StackSize, SERVERSTACK,
TAG_DONE
};
return(muBase->Server = CreateNewProc((struct TagItem *)tags));
}
/*
* Activate the Server by sending the Startup Message
*/
BOOL StartServer(void)
{
return((BOOL)DoPkt(&muBase->Server->pr_MsgPort, ACTION_STARTUP, NULL, NULL, NULL, NULL, NULL));
}
/*
* Kill the Server
*/
BOOL KillServer(void)
{
return((BOOL)SendServerPacket(muSAction_Quit, NULL, NULL, NULL, NULL));
}
/*
* Send a Packet to the Server
*/
LONG SendServerPacket(LONG type, LONG arg1, LONG arg2, LONG arg3, LONG arg4)
{
struct muSPacket pkt;
struct MsgPort *port;
if (port = CreateMsgPort()) {
/*
* Initialise the Server Packet
*/
pkt.Msg.mn_Node.ln_Succ = NULL;
pkt.Msg.mn_Node.ln_Pred = NULL;
pkt.Msg.mn_Node.ln_Type = NULL;
pkt.Msg.mn_Node.ln_Pri = NULL;
pkt.Msg.mn_Node.ln_Name = NULL;
pkt.Msg.mn_ReplyPort = port;
pkt.Msg.mn_Length = sizeof(struct muSPacket);
pkt.Type = type;
pkt.Arg1 = arg1;
pkt.Arg2 = arg2;
pkt.Arg3 = arg3;
pkt.Arg4 = arg4;
pkt.Res1 = NULL;
/*
* Transmit the packet and wait for reply
*/
Forbid();
if (muBase->ServerPort) {
PutMsg(muBase->ServerPort, (struct Message *)&pkt);
Permit();
do
WaitPort(port);
while (GetMsg(port) != (struct Message *)&pkt);
} else
Permit();
DeleteMsgPort(port);
return(pkt.Res1);
} else
return(NULL);
}
/*
* The Server's Process
*/
static void __saveds ServerProcess(void)
{
struct muSPacket *pkt;
BOOL quit = FALSE;
ULONG user;
ULONG signals;
struct DosPacket *spkt;
/*
* Get Startup Message
*/
spkt = WaitPkt();
/*
* Do all necessary initialisations
*/
((struct Process *)SysBase->ThisTask)->pr_WindowPtr = (APTR)-1;
if (((muBase->NotifySig = AllocSignal(-1)) == -1) ||
((muBase->ConsistencySig = AllocSignal(-1)) == -1) || !(muBase->ServerPort = CreateMsgPort()) ||
!(muBase->MonitorPort = CreateMsgPort())) {
ReplyPkt(spkt, DOSFALSE, NULL);
Die(NULL, AN_Unknown | AG_NoSignal);
}
/*
* Reply Startup Message
*/
ReplyPkt(spkt, DOSTRUE, NULL);
InitVolumes();
do {
signals = Wait(1<<muBase->NotifySig | 1<<muBase->ConsistencySig |
1<<muBase->ServerPort->mp_SigBit | 1<<muBase->MonitorPort->mp_SigBit);
if (signals & 1<<muBase->NotifySig)
FreeDefs();
if (signals & 1<<muBase->ConsistencySig) {
FreeVolumes();
InitVolumes();
}
if (signals & 1<<muBase->ServerPort->mp_SigBit)
while (!quit && (pkt = (struct muSPacket *)GetMsg(muBase->ServerPort))) {
switch (pkt->Type) {
case muSAction_Quit:
/*
* Quit
*
*
* Arg1: /
* Arg2: /
* Arg3: /
*
* Res1: BOOL success
*/
quit = TRUE;
pkt->Res1 = TRUE;
/*
* Ensure the Server will be RemTask()ed BEFORE any
* other task will get the processor !!
*/
Forbid();
break;
case muSAction_CheckUser:
/*
* CheckUser
*
*
* Arg1: STRPTR uid
* Arg2: STRPTR pwd
* Arg3: BOOL nopasswd
*
* Res1: struct muPrivUserInfo *info (NULL for failure)
*/
user = GetTaskOwner(pkt->Msg.mn_ReplyPort->mp_SigTask);
pkt->Res1 = (LONG)CheckUser(user, (STRPTR)pkt->Arg1, (STRPTR)pkt->Arg2,
(BOOL)pkt->Arg3, (BOOL)pkt->Arg4);
break;
case muSAction_Passwd:
/*
* Passwd
*
*
* Arg1: STRPTR oldpwd
* Arg2: STRPTR newpwd
* Arg3: /
*
* Res1: BOOL success
*/
user = GetTaskOwner(pkt->Msg.mn_ReplyPort->mp_SigTask);
pkt->Res1 = (LONG)Passwd(user, (STRPTR)pkt->Arg1, (STRPTR)pkt->Arg2);
break;
case muSAction_GetUserInfo:
/*
* GetUserInfo
*
*
* Arg1: struct muPrivUserInfo *info
* Arg2: ULONG keytype
* Arg3: /
*
* Res1: struct muPrivUserInfo *info (NULL for failure)
*/
pkt->Res1 = (LONG)GetUserInfo((struct muPrivUserInfo *)pkt->Arg1, (ULONG)pkt->Arg2);
break;
case muSAction_CheckPasswd:
/*
* CheckPasswd
*
*
* Arg1: STRPTR pwd
* Arg2: /
* Arg3: /
*
* Res1: BOOL success
*/
user = GetTaskOwner(pkt->Msg.mn_ReplyPort->mp_SigTask);
pkt->Res1 = (LONG)CheckPasswd(user, (STRPTR)pkt->Arg1);
break;
case muSAction_PasswdDirLock:
/* PasswdDirLock
*
*
* Arg1: /
* Arg2: /
* Arg3: /
*
* Res1: BPTR lock
*/
if (PasswdDirLock)
pkt->Res1 = DupLock(PasswdDirLock);
break;
case muSAction_ConfigDirLock:
/* ConfigDirLock
*
*
* Arg1: /
* Arg2: /
* Arg3: /
*
* Res1: BPTR lock
*/
if (ConfigDirLock)
pkt->Res1 = DupLock(ConfigDirLock);
break;
case muSAction_GetGroupInfo:
/*
* GetGroupInfo
*
*
* Arg1: struct muPrivGroupInfo *info
* Arg2: ULONG keytype
* Arg3: /
*
* Res1: struct muPrivGroupInfo *info (NULL for failure)
*/
pkt->Res1 = (LONG)GetGroupInfo((struct muPrivGroupInfo *)pkt->Arg1, (ULONG)pkt->Arg2);
break;
default:
break;
}
ReplyMsg((struct Message *)pkt);
}
if (signals & 1<<muBase->MonitorPort->mp_SigBit)
FreeRepliedMonMsg();
} while (!quit);
FreeVolumes();
DeleteMsgPort(muBase->MonitorPort);
DeleteMsgPort(muBase->ServerPort);
FreeSignal(muBase->ConsistencySig);
FreeSignal(muBase->NotifySig);
muBase->MonitorPort = NULL;
muBase->ServerPort = NULL;
muBase->ConsistencySig = NULL;
muBase->Server = NULL;
}
/*
* Check if a user is licensed to login
*/
static struct muPrivUserInfo *CheckUser(ULONG user, STRPTR userid, STRPTR pwd, BOOL nopasswd,
BOOL nolog)
{
BOOL found;
char buffer[12];
struct muPrivUserInfo *info = NULL;
struct muUserDef *def;
UWORD uid;
uid = user>>16;
if (def = GetUserDefs())
do
if ((found = (!strcmp(userid, def->UserID))) && (nopasswd ||
(Encrypt(buffer, pwd, def->UserID) && !strcmp(buffer, def->Password))) &&
(info = muAllocUserInfo()))
FillUserInfo(def, info);
else
def = def->Next;
while (!found && def);
if (info)
CallMonitors(muTrgB_Login, uid, info->Pub.uid, userid);
else
CallMonitors(muTrgB_LoginFail, uid, NULL, userid);
if (!nolog && ((info && (muBase->Config.LogFlags & muLogF_Login)) ||
(!info && (muBase->Config.LogFlags & muLogF_LoginFail)))) {
LONG args[2];
args[0] = uid;
args[1] = (LONG)userid;
if (info)
VLogF(GetLogStr(MSG_LOG_LOGIN), args);
else
VLogF(GetLogStr(MSG_LOG_LOGINFAIL), args);
}
return(info);
}
/*
* Change the Password of a user
*/
static BOOL Passwd(ULONG user, STRPTR oldpwd, STRPTR newpwd)
{
BOOL found;
BOOL changed = FALSE;
UWORD uid, gid;
char buffer[12];
struct muUserDef *def;
uid = user>>16;
gid = user&muMASK_GID;
if (((uid >= muBase->Config.PasswduidLevel) || (gid >= muBase->Config.PasswdgidLevel)) &&
(def = GetUserDefs()))
do
if (found = (def->uid == uid))
changed = Encrypt(buffer, oldpwd, def->UserID) && !strcmp(buffer, def->Password) &&
Encrypt(def->Password, newpwd, def->UserID) && UpdateUserDefs();
else
def = def->Next;
while (!found && def);
if (changed)
CallMonitors(muTrgB_Passwd, uid, NULL, NULL);
else
CallMonitors(muTrgB_PasswdFail, uid, NULL, NULL);
if ((changed && (muBase->Config.LogFlags & muLogF_Passwd)) ||
(!changed && (muBase->Config.LogFlags & muLogF_PasswdFail))) {
LONG args[1];
args[0] = uid;
if (changed)
VLogF(GetLogStr(MSG_LOG_PASSWD), args);
else
VLogF(GetLogStr(MSG_LOG_PASSWDFAIL), args);
}
return(changed);
}
/*
* Get Information about a User
*/
static struct muPrivUserInfo *GetUserInfo(struct muPrivUserInfo *info, ULONG keytype)
{
struct muUserDef *def;
ULONG len;
ULONG count = 0;
if (def = GetUserDefs()) {
switch (keytype) {
case muKeyType_First:
break;
case muKeyType_Next:
while ((count <= info->Count) && (def = def->Next))
count++;
break;
case muKeyType_UserID:
while (strcmp(def->UserID, info->Pub.UserID) && (def = def->Next))
count++;
break;
case muKeyType_uid:
while ((def->uid != info->Pub.uid) && (def = def->Next))
count++;
break;
case muKeyType_gid:
info->Tgid = info->Pub.gid;
while (!Belongs2(def, info->Tgid) && (def = def->Next))
count++;
break;
case muKeyType_gidNext:
while ((count <= info->Count) && (def = def->Next))
count++;
if (def)
while (!Belongs2(def, info->Tgid) && (def = def->Next))
count++;
break;
case muKeyType_UserName:
while (stricmp(def->UserName, info->Pub.UserName) && (def = def->Next))
count++;
break;
case muKeyType_WUserID:
FreeV(info->Pattern);
len = 2*strlen(info->Pub.UserID)+2;
if ((info->Pattern = MAllocV(len)) &&
(ParsePatternNoCase(info->Pub.UserID, info->Pattern, len) != -1))
while (!MatchPatternNoCase(info->Pattern, def->UserID) && (def = def->Next))
count++;
else {
FreeV(info->Pattern);
info->Pattern = NULL;
def = NULL;
}
break;
case muKeyType_WUserIDNext:
if (info->Pattern) {
while ((count <= info->Count) && (def = def->Next))
count++;
if (def)
while (!MatchPatternNoCase(info->Pattern, def->UserID) && (def = def->Next))
count++;
} else
def = NULL;
break;
case muKeyType_WUserName:
FreeV(info->Pattern);
len = 2*strlen(info->Pub.UserName)+2;
if ((info->Pattern = MAllocV(len)) &&
(ParsePatternNoCase(info->Pub.UserName, info->Pattern, len) != -1))
while (!MatchPatternNoCase(info->Pattern, def->UserName) && (def = def->Next))
count++;
else {
FreeV(info->Pattern);
info->Pattern = NULL;
def = NULL;
}
break;
case muKeyType_WUserNameNext:
if (info->Pattern) {
while ((count <= info->Count) && (def = def->Next))
count++;
if (def)
while (!MatchPatternNoCase(info->Pattern, def->UserName) && (def = def->Next))
count++;
} else
def = NULL;
break;
default:
def = NULL;
break;
}
if (def) {
FillUserInfo(def, info);
info->Count = count;
} else
info = NULL;
} else
info = NULL;
return(info);
}
/*
* Checker whether a user belongs to a group
*/
static BOOL Belongs2(struct muUserDef *def, UWORD gid)
{
int i;
if (def->gid == gid)
return(TRUE);
for (i = 0; i < def->NumSecGroups; i++)
if (def->SecGroups[i] == gid)
return(TRUE);
return(FALSE);
}
/*
* Fill in the User Information
*/
static void FillUserInfo(struct muUserDef *def, struct muPrivUserInfo *info)
{
strncpy(info->Pub.UserID, def->UserID, muUSERIDSIZE-1);
info->Pub.UserID[muUSERIDSIZE-1] = '\0';
info->Pub.uid = def->uid;
info->Pub.gid = def->gid;
strncpy(info->Pub.UserName, def->UserName, muUSERNAMESIZE-1);
info->Pub.UserName[muUSERNAMESIZE-1] = '\0';
strncpy(info->Pub.HomeDir, def->HomeDir, muHOMEDIRSIZE-1);
info->Pub.HomeDir[muHOMEDIRSIZE-1] = '\0';
if (info->Pub.NumSecGroups)
Free(info->Pub.SecGroups, info->Pub.NumSecGroups*sizeof(UWORD));
if (def->NumSecGroups && (info->Pub.SecGroups = MAlloc(def->NumSecGroups*sizeof(UWORD)))) {
info->Pub.NumSecGroups = def->NumSecGroups;
CopyMem(def->SecGroups, info->Pub.SecGroups, def->NumSecGroups*sizeof(UWORD));
} else {
info->Pub.NumSecGroups = 0;
info->Pub.SecGroups = NULL;
}
strncpy(info->Pub.Shell, def->Shell, muSHELLSIZE-1);
info->Password = !!strlen(def->Password);
}
/*
* Check the Password of a User
*/
static BOOL CheckPasswd(ULONG user, STRPTR pwd)
{
BOOL found;
BOOL valid = FALSE;
UWORD uid;
char buffer[12];
struct muUserDef *def;
uid = user>>16;
if (def = GetUserDefs())
do
if (found = (def->uid == uid))
valid = Encrypt(buffer, pwd, def->UserID) && !strcmp(buffer, def->Password);
else
def = def->Next;
while (!found && def);
if (valid)
CallMonitors(muTrgB_CheckPasswd, uid, NULL, NULL);
else
CallMonitors(muTrgB_CheckPasswdFail, uid, NULL, NULL);
if ((valid && (muBase->Config.LogFlags & muLogF_CheckPasswd)) ||
(!valid && (muBase->Config.LogFlags & muLogF_CheckPasswdFail))) {
LONG args[1];
args[0] = uid;
if (valid)
VLogF(GetLogStr(MSG_LOG_CHECKPASSWD), args);
else
VLogF(GetLogStr(MSG_LOG_CHECKPASSWDFAIL), args);
}
return(valid);
}
/*
* Get Information about a Group
*/
static struct muPrivGroupInfo *GetGroupInfo(struct muPrivGroupInfo *info, ULONG keytype)
{
struct muGroupDef *def;
ULONG len;
ULONG count = 0;
if (def = GetGroupDefs()) {
switch (keytype) {
case muKeyType_First:
break;
case muKeyType_Next:
while ((count <= info->Count) && (def = def->Next))
count++;
break;
case muKeyType_GroupID:
while (strcmp(def->GroupID, info->Pub.GroupID) && (def = def->Next))
count++;
break;
case muKeyType_gid:
while ((def->gid != info->Pub.gid) && (def = def->Next))
count++;
break;
case muKeyType_GroupName:
while (stricmp(def->GroupName, info->Pub.GroupName) && (def = def->Next))
count++;
break;
case muKeyType_WGroupID:
FreeV(info->Pattern);
len = 2*strlen(info->Pub.GroupID)+2;
if ((info->Pattern = MAllocV(len)) &&
(ParsePatternNoCase(info->Pub.GroupID, info->Pattern, len) != -1))
while (!MatchPatternNoCase(info->Pattern, def->GroupID) && (def = def->Next))
count++;
else {
FreeV(info->Pattern);
info->Pattern = NULL;
def = NULL;
}
break;
case muKeyType_WGroupIDNext:
if (info->Pattern) {
while ((count <= info->Count) && (def = def->Next))
count++;
if (def)
while (!MatchPatternNoCase(info->Pattern, def->GroupID) && (def = def->Next))
count++;
} else
def = NULL;
break;
case muKeyType_WGroupName:
FreeV(info->Pattern);
len = 2*strlen(info->Pub.GroupName)+2;
if ((info->Pattern = MAllocV(len)) &&
(ParsePatternNoCase(info->Pub.GroupName, info->Pattern, len) != -1))
while (!MatchPatternNoCase(info->Pattern, def->GroupName) && (def = def->Next))
count++;
else {
FreeV(info->Pattern);
info->Pattern = NULL;
def = NULL;
}
break;
case muKeyType_WGroupNameNext:
if (info->Pattern) {
while ((count <= info->Count) && (def = def->Next))
count++;
if (def)
while (!MatchPatternNoCase(info->Pattern, def->GroupName) && (def = def->Next))
count++;
} else
def = NULL;
break;
case muKeyType_MgrUid:
while ((def->MgrUid != info->Pub.MgrUid) && (def = def->Next))
count++;
break;
case muKeyType_MgrUidNext:
while ((count <= info->Count) && (def = def->Next))
count++;
if (def)
while ((def->MgrUid != info->Pub.MgrUid) && (def = def->Next))
count++;
break;
default:
def = NULL;
break;
}
if (def) {
FillGroupInfo(def, info);
info->Count = count;
} else
info = NULL;
} else
info = NULL;
return(info);
}
/*
* Fill in the Group Information
*/
static void FillGroupInfo(struct muGroupDef *def, struct muPrivGroupInfo *info)
{
strncpy(info->Pub.GroupID, def->GroupID, muGROUPIDSIZE-1);
info->Pub.GroupID[muGROUPIDSIZE-1] = '\0';
info->Pub.gid = def->gid;
info->Pub.MgrUid = def->MgrUid;
strncpy(info->Pub.GroupName, def->GroupName, muGROUPNAMESIZE-1);
info->Pub.GroupName[muGROUPNAMESIZE-1] = '\0';
}